package com.google.code.jholidays.events.parameters;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.util.Calendar;

import org.junit.Test;

public class DateParametersTest {

    @Test(expected = IllegalArgumentException.class)
    public void testErrorLowMonth() {
	int dayOfWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);

	int month = Calendar.getInstance().getActualMinimum(Calendar.MONTH);

	DateParameters params = new DateParameters(dayOfWeek, month - 1,
		DayOfWeekOrder.First);
	assertNull(params);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testErrorHighMonth() {
	int dayOfWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);

	int month = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	DateParameters params = new DateParameters(dayOfWeek, month + 1,
		DayOfWeekOrder.First);
	assertNull(params);
    }

    @Test
    public void testNormalMonth() {
	int dayOfWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);

	int month = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	for (int i = month; i <= max; ++i) {
	    DateParameters params = new DateParameters(dayOfWeek, i,
		    DayOfWeekOrder.First);
	    assertNotNull(params);
	}
    }

    public void testErrorLowDayOfWeek() {
	int min = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	int dayOfWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);

	int cnt = 0;

	for (int i = min; i <= max; ++i) {
	    try {
		DateParameters params = new DateParameters(dayOfWeek - 1, min,
			DayOfWeekOrder.First);
		assertNull(params);
	    } catch (Exception e) {
		++cnt;
	    }
	}

	assertEquals((Integer) cnt, (Integer) (max - min));
    }

    public void testErrorHighDayOfWeek() {
	int min = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	int dayOfWeek = Calendar.getInstance().getActualMaximum(
		Calendar.DAY_OF_WEEK);

	int cnt = 0;

	for (int i = min; i <= max; ++i) {
	    try {
		DateParameters params = new DateParameters(dayOfWeek + 1, min,
			DayOfWeekOrder.First);
		assertNull(params);
	    } catch (Exception e) {
		++cnt;
	    }
	}

	assertEquals((Integer) cnt, (Integer) (max - min));
    }

    @Test
    public void testNormalDayOfWeek() {
	int month_min = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int month_max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	int dayOfWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);
	int max = Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_WEEK);

	for (int j = month_min; j <= month_max; ++j) {
	    for (int i = dayOfWeek; i <= max; ++i) {
		DateParameters params = new DateParameters(i, j,
			DayOfWeekOrder.First);
		assertNotNull(params);
	    }
	}
    }

    @Test
    public void testNormalOrder() {
	int month_min = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int month_max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	int min_dayWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);
	int max_dayWeek = Calendar.getInstance().getActualMaximum(
		Calendar.DAY_OF_WEEK);

	int currentYear = Calendar.getInstance().get(Calendar.YEAR);

	for (int i = month_min; i <= month_max; ++i) {

	    for (int j = min_dayWeek; j <= max_dayWeek; ++j) {
		Calendar c = Calendar.getInstance();
		c.clear();
		c.set(currentYear, i, 1);

		c.set(Calendar.DAY_OF_WEEK, j);

		DateParameters params = new DateParameters(j, i,
			DayOfWeekOrder.First);
		assertNotNull(params);
		params = new DateParameters(j, i, DayOfWeekOrder.Second);
		assertNotNull(params);
		params = new DateParameters(j, i, DayOfWeekOrder.Third);
		assertNotNull(params);
		params = new DateParameters(j, i, DayOfWeekOrder.Fourth);
		assertNotNull(params);
		params = new DateParameters(j, i, DayOfWeekOrder.Last);
		assertNotNull(params);
	    }
	}
    }

    @Test
    public void testGetDayOfWeek() {
	int month_min = Calendar.getInstance().getActualMinimum(Calendar.MONTH);
	int month_max = Calendar.getInstance().getActualMaximum(Calendar.MONTH);

	int min_dayWeek = Calendar.getInstance().getActualMinimum(
		Calendar.DAY_OF_WEEK);
	int max_dayWeek = Calendar.getInstance().getActualMaximum(
		Calendar.DAY_OF_WEEK);

	int currentYear = Calendar.getInstance().get(Calendar.YEAR);

	for (int i = month_min; i <= month_max; ++i) {

	    for (int j = min_dayWeek; j <= max_dayWeek; ++j) {
		Calendar c = Calendar.getInstance();
		c.clear();
		c.set(currentYear, i, 1);

		c.set(Calendar.DAY_OF_WEEK, j);

		DateParameters params = new DateParameters(j, i,
			DayOfWeekOrder.First);
		assertNotNull(params);
		assertEquals(j, params.getDayOfWeek());
		assertEquals(i, params.getMonth());
		assertEquals(DayOfWeekOrder.First, params.getOrder());

		params = new DateParameters(j, i, DayOfWeekOrder.Second);
		assertNotNull(params);
		assertEquals(j, params.getDayOfWeek());
		assertEquals(i, params.getMonth());
		assertEquals(DayOfWeekOrder.Second, params.getOrder());

		params = new DateParameters(j, i, DayOfWeekOrder.Third);
		assertNotNull(params);
		assertEquals(j, params.getDayOfWeek());
		assertEquals(i, params.getMonth());
		assertEquals(DayOfWeekOrder.Third, params.getOrder());

		params = new DateParameters(j, i, DayOfWeekOrder.Fourth);
		assertNotNull(params);
		assertEquals(j, params.getDayOfWeek());
		assertEquals(i, params.getMonth());
		assertEquals(DayOfWeekOrder.Fourth, params.getOrder());

		params = new DateParameters(j, i, DayOfWeekOrder.Last);
		assertNotNull(params);
		assertEquals(j, params.getDayOfWeek());
		assertEquals(i, params.getMonth());
		assertEquals(DayOfWeekOrder.Last, params.getOrder());
	    }
	}
    }

}
